/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package SwingAnimation;

import GUIUtilities.ColorUtilities;
import java.awt.Color;
import java.util.Timer;
import java.util.Vector;
import javax.swing.JComponent;

/**
 *
 * @author Heather
 */
public class ColorPulser implements AnimationInterface
{

  /**
   * @return the pulseOption
   */
  public PulseOptions getPulseOption()
  {
    return pulseOption;
  }

  /**
   * @param pulseOption the pulseOption to set
   */
  public void setPulseOption(PulseOptions pulseOption)
  {
    this.pulseOption = pulseOption;
  }

  /**
   * @return the toPulse
   */
  public JComponent getToPulse()
  {
    return toPulseComponent;
  }

  /**
   * @param toPulse the toPulse to set
   */
  public void setToPulse(JComponent toPulse)
  {
    this.toPulseComponent = toPulse;
  }

  /**
   * @return the originalColor
   */
  public Color getOriginalColor()
  {
    return originalColor;
  }

  /**
   * @param originalColor the originalColor to set
   */
  public void setOriginalColor(Color originalColor)
  {
    this.originalColor = originalColor;
  }

  /**
   * @return the dimmerAllowed
   */
  public boolean isDimmerAllowed()
  {
    return dimmerAllowed;
  }

  /**
   * @param dimmerAllowed the dimmerAllowed to set
   */
  public void setDimmerAllowed(boolean dimmerAllowed)
  {
    this.dimmerAllowed = dimmerAllowed;
  }

  /**
   * @return the steps
   */
  public Vector<Color> getSteps()
  {
    return steps;
  }

  /**
   * @param steps the steps to set
   */
  public void setSteps(Vector<Color> steps)
  {
    this.steps = steps;
  }

  /**
   * @return the stepIndex
   */
  public int getStepIndex()
  {
    return stepIndex;
  }

  /**
   * @param stepIndex the stepIndex to set
   */
  public void setStepIndex(int stepIndex)
  {
    this.stepIndex = stepIndex;
  }

  /**
   * @return the animationTimer
   */
  public Timer getAnimationTimer()
  {
    return animationTimer;
  }

  /**
   * @param animationTimer the animationTimer to set
   */
  public void setAnimationTimer(Timer animationTimer)
  {
    this.animationTimer = animationTimer;
  }

  /**
   * @return the animationInterval
   */
  public int getAnimationInterval()
  {
    return animationInterval;
  }

  /**
   * @param animationInterval the animationInterval to set
   */
  public void setAnimationInterval(int animationInterval)
  {
    this.animationInterval = animationInterval;
  }

  /**
   * @return the colorStep
   */
  public int getColorStep()
  {
    return colorStep;
  }

  /**
   * @param colorStep the colorStep to set
   */
  public void setColorStep(int colorStep)
  {
    this.colorStep = colorStep;
  }

  /**
   * @return the numberOfShades
   */
  public int getNumberOfShades()
  {
    return numberOfShades;
  }

  /**
   * @param numberOfShades the numberOfShades to set
   */
  public void setNumberOfShades(int numberOfShades)
  {
    this.numberOfShades = numberOfShades;
  }

  public enum PulseOptions
  {

    darken, lighten
  };
  private PulseOptions pulseOption = PulseOptions.lighten;
  private boolean toPulseIsComponent = true;
  private JComponent toPulseComponent;
  private ColorPulserInterface toPulseInterface;
  // indicates the original color
  private Color originalColor;
  // indicates whether or not the animation allows the color to get darker than the original
  private boolean dimmerAllowed = true;
  private Vector<Color> steps = new Vector<Color>();
  private int stepIndex = 0;
  private Timer animationTimer = new Timer();
  // how often to call the next step
  private int animationInterval = 50;
  private int colorStep = 30;
  private int numberOfShades = 5;

  public ColorPulser(JComponent toPulse)
  {
    this.toPulseComponent = toPulse;
    originalColor = toPulse.getBackground();
    setupAnimationSteps();
  }

  public ColorPulser(JComponent toPulse, PulseOptions pulseOption)
  {
    this.pulseOption = pulseOption;
    this.toPulseComponent = toPulse;
    originalColor = toPulse.getBackground();
    setupAnimationSteps();
  }

  public ColorPulser(ColorPulserInterface toPulse, Color originalColor)
  {
    toPulseIsComponent = false;
    this.toPulseInterface = toPulse;
    this.originalColor = originalColor;
    setupAnimationSteps();
  }

  public ColorPulser(ColorPulserInterface toPulse, Color originalColor, PulseOptions pulseOption)
  {
    toPulseIsComponent = false;
    this.pulseOption = pulseOption;
    this.toPulseInterface = toPulse;
    this.originalColor = originalColor;
    setupAnimationSteps();
  }

  public void setToFastBlinking()
  {
    stopAnimation();
    colorStep = 30;
    numberOfShades = 5;
    setupAnimationSteps();
  }

  public void setToReallyFastBlinking()
  {
    stopAnimation();
    colorStep = 80;
    numberOfShades = 2;
    setupAnimationSteps();
  }

  public void setToSlowPhasing()
  {
    stopAnimation();
    colorStep = 3;
    numberOfShades = 50;
    setupAnimationSteps();
  }

  public void setToMediumPhasing()
  {
    stopAnimation();
    colorStep = 3;
    numberOfShades = 30;
    setupAnimationSteps();
  }

  private void setupAnimationSteps()
  {
    steps.clear();
    Color currentColor = originalColor;

    Vector<Color> alteredColors = new Vector<Color>();

    for (int i = 0; i < numberOfShades; i++)
    {
      if (pulseOption == PulseOptions.darken)
      {
        currentColor = ColorUtilities.darkenColor(currentColor, colorStep);
      }
      else if (pulseOption == PulseOptions.lighten)
      {
        currentColor = ColorUtilities.lightenColor(currentColor, colorStep);
      }
      alteredColors.add(currentColor);
    }

    for (int i = 0; i < alteredColors.size(); i++)
    {
      steps.add(alteredColors.get(i));
    }

    for (int i = alteredColors.size() - 2; i >= 0; i--)
    {
      steps.add(alteredColors.get(i));
    }

    steps.add(originalColor);
  }

  // returns true if the next animation is valid, false if not
  public boolean showNextAnimation()
  {
    stepIndex++;
    if (stepIndex >= steps.size())
    {
      stepIndex = 0;
    }

    Color toShow = steps.get(stepIndex);
    if (toPulseIsComponent)
    {
      toPulseComponent.setBackground(toShow);
    }
    else
    {
      toPulseInterface.setColor(toShow);
    }

    return true;
  }

  // paints the animation
  public void paintAnimation()
  {
    if (toPulseIsComponent)
    {
      toPulseComponent.repaint();
    }
    else
    {
      toPulseInterface.repaint();
    }
  }

  public void startAnimation()
  {
    animationTimer.scheduleAtFixedRate(new AnimationAnimator(this), 0, animationInterval);
  }

  public void stopAnimation()
  {
    animationTimer.cancel();
    animationTimer = new Timer();
    if (toPulseIsComponent)
    {
      toPulseComponent.repaint();
    }
    else
    {
      toPulseInterface.repaint();
    }
  }
}
